<?php

namespace app\api\controller;

use app\api\controller\UnauthorizedException;
use app\api\controller\Send;
use think\Exception;
use think\Request;
use think\Db;
use think\Cache;
use app\common\model\ClientModel as OauthModel;
use app\common\model\ApiBuyModel;

class Oauth
{
    use Send;
    /**
     * 过期时间秒数
     * @var int
     */
    public static $expires = 72000;

    /**
     * 客户端信息
     */
    public $clientInfo;
    /**
     * 认证授权 通过用户信息和路由
     * @param Request $request
     * @return \Exception|UnauthorizedException|mixed|Exception
     * @throws UnauthorizedException
     */
    final function authenticate()
    {
        try {
            //验证授权
            $clientInfo = $this->getClient();

            //配置不要鉴权的方法白名单库
//            $method = $this->request->controller().'/'.$this->request->action().'/'.strtolower($this->request->method());
//            $api = Api::get(['method' => $method,'status'=>1]);
//            if( $api ){
//                $api = $api->toArray();
//                $checkclient = true;
//                if( $api['is_white'] == 0 ){
//                    $checkclient = $this->certification($clientInfo);
//                }
//                if( $api['price']>0 ){
//                    $checkclient = $this->checkBuy($clientInfo,$api);
//                }
//            }else{
//                return $this->returnmsg(402,'method is not exist.');
//            }
            $checkclient = $this->certification($clientInfo);  //启用上面白名单库后请注释当前行


            if($checkclient){
                return $clientInfo;
            }
        } catch (Exception $e) {
            return $this->returnmsg(402,'Invalid1 authentication credentials.');
        }
    }

    /**
     * 获取用户信息
     * @param Request $request
     * @return $this
     * @throws UnauthorizedException
     */
    public function getClient()
    {
        //获取头部信息
        try {
            $request = Request::instance();

//            $header = $request->header();   //获取请求中的authentication字段，值形式为USERID asdsajh..这种形式
//            $authorization =$header['authentication'];   //获取请求中的authentication字段，值形式为USERID asdsajh..这种形式

            $param = $request->param();
            $authorization =$param['authentication'];
            $authorization = explode(" ", $authorization);        //explode分割，获取后面一窜base64加密数据
            $authorizationInfo  = explode(":", base64_decode($authorization[1]));  //对base_64解密，获取到用:拼接的自字符串，然后分割，可获取appid、accesstoken、uid这三个参数
            $clientInfo['uid'] = $authorizationInfo[2];
            $clientInfo['appid'] = $authorizationInfo[0];
            $clientInfo['access_token'] = $authorizationInfo[1];
        } catch (Exception $e) {
            return $this->returnmsg(402,$e.'Invalid authentication credentials');
        }
        return $clientInfo;
    }

    /**
     * 获取用户信息后 验证权限
     * @return mixed
     */
    public function certification($data = []){
        $client = OauthModel::get(['appid' => $data['appid'],'status'=>1]);
        if(empty($client)){
             return $this->returnmsg(402,'access_token does not match appid');
         }
        $client = $client->toArray();
        if($client['expire_time'] <= time()){
             return $this->returnmsg(402,'access_token expired');
         }
        return true;
    }

    /**
     * 生成签名
     * _字符开头的变量不参与签名
     */
    public function makeSign ($data = [],$app_secret = '')
    {   
        unset($data['version']);
        unset($data['signature']);
        foreach ($data as $k => $v) {
            if(substr($data[$k],0,1) == '_'){
                unset($data[$k]);
            }
        }
        return $this->_getOrderMd5($data,$app_secret);
    }

    /**
     * 计算ORDER的MD5签名
     */
    private function _getOrderMd5($params = [] , $app_secret = '') {
        $params['key'] = $app_secret;
        ksort($params);
        return strtolower(md5(urldecode(http_build_query($params))));
    }


    /**
     * 判断是否是付费接口
     * @return mixed
     */
    public function checkBuy($clientInfo=[],$api=[]){
        $buyInfo = ApiBuyModel::get(['uid' => $clientInfo['uid'],'api_id'=>$api['id'],'expire_time'=>['gt',time()]]);
        if(empty($buyInfo)){
            return $this->returnmsg(402,'api does not payment');
        }
        return true;
    }

}